# 指定文件编码为UTF-8
# coding: utf-8

"""
gradient_check.py 功能说明：
1. 实现卷积神经网络(CNN)的梯度检查功能
2. 比较数值梯度与解析梯度的差异
3. 验证反向传播实现的正确性
4. 使用随机输入数据进行测试
5. 输出各层梯度差异的平均值

关键点：
- 数值梯度计算使用中心差分法
- 解析梯度通过反向传播计算
- 比较两种梯度计算方式的差异
- 适用于卷积层、全连接层等各层参数
- 差异值越小说明反向传播实现越准确
"""

# 导入NumPy数值计算库
import numpy as np
# 从simple_convnet导入简单卷积网络类
from simple_convnet import SimpleConvNet

# 初始化简单卷积网络
network = SimpleConvNet(
    input_dim=(1, 10, 10),  # 输入数据维度(通道数1, 高10, 宽10)
    conv_param = {
        'filter_num': 10,    # 卷积核数量
        'filter_size': 3,    # 卷积核尺寸
        'pad': 0,           # 填充大小
        'stride': 1         # 步长
    },
    hidden_size=10,         # 隐藏层神经元数量
    output_size=10,         # 输出层神经元数量
    weight_init_std=0.01    # 权重初始化标准差
)

# 生成随机输入数据(1个样本, 1通道, 10x10大小)
X = np.random.rand(100).reshape((1, 1, 10, 10))
# 生成随机标签数据(1个样本, 类别1)
T = np.array([1]).reshape((1,1))

# 计算数值梯度(使用中心差分法)
grad_num = network.numerical_gradient(X, T)
# 计算解析梯度(通过反向传播)
grad = network.gradient(X, T)

# 比较两种梯度计算结果的差异
for key, val in grad_num.items():
    # 计算并打印各层参数梯度的平均绝对误差
    print(key, np.abs(grad_num[key] - grad[key]).mean())

"""
预期输出：
各层参数(W1, b1, W2, b2等)的梯度差异平均值
理想情况下差异应非常小(如1e-7量级)

注意事项：
1. 差异值过大可能表明反向传播实现有误
2. 可以调整输入数据大小观察差异变化
3. 网络结构变化时需要重新验证梯度
4. 训练前建议进行梯度检查确保正确性
5. 数值梯度计算较慢，仅用于调试
"""
